package com.lanmaoly.test.thread;

import com.lanmaoly.test.NamedThreadFactory;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.*;

/**
 * 五种线程池
 *
 * @author Administrator
 */
public class ThreadTest1 {

    public static void main(String[] args) {
        try {
            Constructor<SingletonTest> constructor = SingletonTest.class.getDeclaredConstructor();
            constructor.setAccessible(true);
            SingletonTest singletonTest = constructor.newInstance();
            singletonTest.print();

            Class<?> aClass = Class.forName("com.lanmaoly.test.thread.SingletonTest");
            Constructor<?> constructor1 = aClass.getDeclaredConstructor();
            constructor1.setAccessible(true);
            Object instance = constructor1.newInstance();
            if (instance instanceof SingletonTest) {
                SingletonTest test = (SingletonTest) instance;
                test.print();
            }
        } catch (NoSuchMethodException | InstantiationException | IllegalAccessException
                | InvocationTargetException | ClassNotFoundException e) {
            e.printStackTrace();
        }
        System.out.println("-----------------------------------------------------------------------");
        ExecutorService service = newFixedThreadPool(5, "weew");
        for (int i = 0; i < 5; i++) {
            Future<SingletonTest> future = service.submit(SingletonTest::getInstance);
            SingletonTest test = null;
            try {
                test = future.get();
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
            if (test != null) {
                test.print();
            }
        }
        service.shutdown();

        String join = String.join(",", "1", "2", "3", "4");
        System.out.println(join);
    }

    /**
     * （1）线程池中的线程处于一定的量，可以很好的控制线程的并发量
     * （2）线程可以重复被使用，在显示关闭之前，都将一直存在
     * （3）超出一定量的线程被提交时候需在队列中等待
     *
     * @param nTheads 线程数量 核心与最大
     * @param name    线程名称
     * @return ExecutorService
     */
    private static ExecutorService newFixedThreadPool(int nTheads, String name) {
        ThreadFactory threadFactory;
        if (name == null || name.length() == 0) {
            threadFactory = Executors.defaultThreadFactory();
        } else {
            threadFactory = new NamedThreadFactory(name);
        }
        ExecutorService executorService = Executors.newFixedThreadPool(nTheads, threadFactory);
        // 实际创建方式
        ExecutorService executor = new ThreadPoolExecutor(nTheads, nTheads, 0L,
                TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), threadFactory);
        return executorService;
    }

    /**
     * （1）线程池中数量没有固定，初始为0，可达到最大值（Interger. MAX_VALUE）
     * （2）线程池中的线程可进行缓存重复利用和回收（回收默认时间为60s）
     * （3）当线程池中，没有可用线程，会重新创建一个线程
     *
     * @param name 线程名称
     * @return ExecutorService
     */
    private static ExecutorService newCachedThreadPool(String name) {
        ThreadFactory threadFactory;
        if (name == null || name.length() == 0) {
            threadFactory = Executors.defaultThreadFactory();
        } else {
            threadFactory = new NamedThreadFactory(name);
        }
        ExecutorService executorService = Executors.newCachedThreadPool(threadFactory);
        ThreadPoolExecutor executor = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L,
                TimeUnit.SECONDS, new SynchronousQueue<>(), threadFactory);
        return executorService;
    }

    /**
     * （1）线程池中具有指定数量的线程，即便是空线程也将保留
     * （2）可定时或者延迟执行线程活动
     *
     * @param corePoolSize 核心线程数 最大为Integer.MAX_VALUE
     * @param name         线程名称
     * @return ExecutorService
     */
    private static ExecutorService newScheduledThreadPool(int corePoolSize, String name) {
        ThreadFactory threadFactory;
        if (name == null || name.length() == 0) {
            threadFactory = Executors.defaultThreadFactory();
        } else {
            threadFactory = new NamedThreadFactory(name);
        }
        ExecutorService executorService = Executors.newScheduledThreadPool(corePoolSize, threadFactory);
//        new ThreadPoolExecutor(corePoolSize, Integer.MAX_VALUE, 0,
//                TimeUnit.MILLISECONDS, "内部实现的delayedqueue", threadFactory);
        return executorService;
    }

    /**
     * （1）线程池中最多执行1个线程，之后提交的线程活动将会排在队列中以此执行
     *
     * @return ExecutorService
     */
    private static ExecutorService newSingleThreadExecutor(String name) {
        ThreadFactory threadFactory;
        if (name == null || name.length() == 0) {
            threadFactory = Executors.defaultThreadFactory();
        } else {
            threadFactory = new NamedThreadFactory(name);
        }
        ExecutorService executorService = Executors.newSingleThreadExecutor(threadFactory);
        return executorService;
    }

    /**
     * （1）线程池中最多执行1个线程，之后提交的线程活动将会排在队列中以此执行
     * （2）可定时或者延迟执行线程活动
     *
     * @return ExecutorService
     */
    private static ExecutorService newSingleThreadScheduledExecutor(String name) {
        ThreadFactory threadFactory;
        if (name == null || name.length() == 0) {
            threadFactory = Executors.defaultThreadFactory();
        } else {
            threadFactory = new NamedThreadFactory(name);
        }
        ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(threadFactory);
        return executorService;
    }
}
